﻿using HtmlAgilityPack;
using System.Collections;
using System.ComponentModel;
using System.Reflection;
using System.Text.RegularExpressions;
using Zhp.Common.Helper;
using Zhp.Entity.Message.Email;
using Zhp.IService.Message.Email;
using Zhp.Model.Message.Email;

namespace Zhp.Service.Message.Email
{
    public class EmailTemplateRender : IEmailTemplateRender
    {
        public EmailTemplateRender()
        {
        }

        public async Task<EmailTemplate> RenderTemplateAsync(EmailTemplate tpl, object renderData)
        {
            var (bodyTemplate, dict) = ConvertToDict(renderData, tpl.Body);

            foreach (var item in dict)
            {
                tpl.Subject = tpl.Subject.Replace(item.Key, item.Value);
                bodyTemplate = bodyTemplate.Replace(item.Key, item.Value);
            }

            tpl.Body = bodyTemplate;

            return await Task.FromResult(tpl);
        }

        private (string, Dictionary<string, string>) ConvertToDict(object renderData, string bodyTemplate)
        {
            var dict = new Dictionary<string, string>();
            if (renderData is IList dataList)
            {
                HtmlDocument doc = new HtmlDocument();
                doc.LoadHtml(bodyTemplate);
                var tableNode = doc.DocumentNode.SelectNodes("table").FirstOrDefault();
                if (tableNode != null)
                {
                    HtmlNode tbodyNode = null;
                    HtmlNode trNodeTpl = null;
                    if (tableNode != null && tableNode.HasChildNodes)
                    {
                        // 处理table边框
                        (tableNode, tbodyNode, trNodeTpl) = AddTableBorder(tableNode, tbodyNode, trNodeTpl);
                    }
                    int index = 0;
                    foreach (var item in dataList)
                    {
                        // 复制模板，然后根据数据增加模板
                        AppendTableRow(doc, trNodeTpl, tbodyNode, index);
                        foreach (var itemProperty in item.GetType().GetProperties())
                        {
                            var itemValue = itemProperty.GetValue(item)?.ToString() ?? string.Empty;
                            dict.Add($"{{{itemProperty.Name}.{index}}}", itemValue);
                        }
                        index++;
                    }
                    bodyTemplate = doc.DocumentNode.OuterHtml;
                }
            }
            else
            {
                var properties = renderData.GetType().GetProperties();
                foreach (var property in properties)
                {
                    var propValue = property.GetValue(renderData);
                    if (propValue is IList propList)
                    {
                        HtmlDocument doc = new HtmlDocument();
                        doc.LoadHtml(bodyTemplate);
                        var tableNode = doc.DocumentNode.SelectNodes("table").FirstOrDefault(x => x.InnerText.Contains(property.Name));
                        if (tableNode != null)
                        {
                            HtmlNode tbodyNode = null;
                            HtmlNode trNodeTpl = null;
                            if (tableNode != null && tableNode.HasChildNodes)
                            {
                                // 处理table边框
                                (tableNode, tbodyNode, trNodeTpl) = AddTableBorder(tableNode, tbodyNode, trNodeTpl);
                            }
                            int index = 0;
                            foreach (var item in propList)
                            {
                                // 复制模板，然后根据数据增加模板
                                AppendTableRow(doc, trNodeTpl, tbodyNode, index);
                                foreach (var itemProperty in item.GetType().GetProperties())
                                {
                                    var itemValue = itemProperty.GetValue(item)?.ToString() ?? string.Empty;
                                    dict.Add($"{{{property.Name}.{itemProperty.Name}.{index}}}", itemValue);
                                }
                                index++;
                            }
                            bodyTemplate = doc.DocumentNode.OuterHtml;
                        }
                    }
                    else
                    {
                        dict.Add($"{{{property.Name}}}", propValue?.ToString() ?? string.Empty);
                    }
                }
            }
            return (bodyTemplate, dict);
        }

        /// <summary>
        /// 添加表格边框
        /// </summary>
        /// <param name="tableNode"></param>
        /// <param name="tbodyNode"></param>
        /// <param name="trNodeTpl"></param>
        private (HtmlNode tableNode, HtmlNode tbodyNode, HtmlNode trNodeTpl) AddTableBorder(HtmlNode tableNode, HtmlNode tbodyNode, HtmlNode trNodeTpl)
        {
            tableNode.SetAttributeValue("border", "1");
            tableNode.Attributes["style"].Value += "border-collapse:collapse;";
            tbodyNode = tableNode.SelectSingleNode("tbody");
            trNodeTpl = tbodyNode.LastChild;
            tbodyNode.LastChild.Remove();
            return (tableNode, tbodyNode, trNodeTpl);
        }

        /// <summary>
        /// 复制模板，然后根据数据增加模板
        /// </summary>
        /// <param name="doc"></param>
        /// <param name="trNodeTpl"></param>
        /// <param name="tbodyNode"></param>
        /// <param name="index"></param>
        private void AppendTableRow(HtmlDocument doc, HtmlNode trNodeTpl, HtmlNode tbodyNode, int index)
        {
            // 复制模板，然后根据数据增加模板
            var trNode = trNodeTpl.CloneNode(true);
            var tdNodeList = trNode.ChildNodes.ToList();
            trNode.RemoveAllChildren();
            foreach (var td in tdNodeList)
            {
                // 定义正则表达式模式，匹配 {...} 中的任何内容
                string pattern = @"\{([^}]+)\}";
                // 使用 MatchEvaluator 来自定义替换逻辑
                string replacedText = Regex.Replace(td.InnerText, pattern, match =>
                {
                    // 提取 {} 中的内容
                    string content = match.Groups[1].Value;
                    // 在内容后面添加 .1
                    return $"{{{content}.{index}}}";
                });
                td.RemoveAllChildren();
                td.AppendChild(doc.CreateTextNode(replacedText));

                trNode.AppendChild(td);
            }
            tbodyNode.AppendChild(trNode);
        }

        public async Task<List<TemplateVariableModel>> QueryVariableClass()
        {
            var list = new List<TemplateVariableModel>();
            var types = GetVariableClassTypes();
            foreach (var item in types)
            {
                var attr = item.GetCustomAttribute<DisplayNameAttribute>();
                if (attr != null)
                {
                    list.Add(new TemplateVariableModel
                    {
                        Text = attr != null ? attr.DisplayName : item.Name,
                        Value = item.FullName
                    });
                }
            }
            return await Task.FromResult(list);
        }

        public async Task<List<TemplateVariableModel>> QueryVariable(string variableClass)
        {
            var list = new List<TemplateVariableModel>();
            if (string.IsNullOrEmpty(variableClass))
            {
                return list;
            }
            var type = GetVariableClassType(variableClass);
            var props = type.GetProperties();
            foreach (var prop in props)
            {
                if (typeof(IList).IsAssignableFrom(prop.PropertyType))
                {
                    var propAttr = prop.GetCustomAttribute<DisplayNameAttribute>();
                    var listPropType = prop.PropertyType.GetGenericArguments()[0];
                    foreach (var item in listPropType.GetProperties())
                    {
                        var attr = item.GetCustomAttribute<DisplayNameAttribute>();
                        list.Add(new TemplateVariableModel
                        {
                            Text = propAttr != null ? $"{propAttr.DisplayName}.{attr?.DisplayName}" : attr?.DisplayName,
                            Value = $"{{{prop.Name}.{item.Name}}}"
                        });
                    }
                }
                else
                {
                    var attr = prop.GetCustomAttribute<DisplayNameAttribute>();
                    list.Add(new TemplateVariableModel
                    {
                        Text = attr?.DisplayName,
                        Value = $"{{{prop.Name}}}"
                    });
                }
            }
            return await Task.FromResult(list);
        }

        /// <summary>
        /// 根据类型生成默认json数据
        /// </summary>
        /// <param name="variableClass"></param>
        /// <returns></returns>
        public async Task<TemplateVariableJson> QueryDefaultJson(string variableClass)
        {
            var json = new TemplateVariableJson();
            var type = GetVariableClassType(variableClass);
            object obj = Activator.CreateInstance(type);
            SetDefaultValues(obj);
            json.Json = obj.ToJson();
            return await Task.FromResult(json);
        }

        private void SetDefaultValues(object obj)
        {
            Type type = obj.GetType();
            PropertyInfo[] properties = type.GetProperties();
            foreach (PropertyInfo property in properties)
            {
                if (typeof(IList).IsAssignableFrom(property.PropertyType))
                {
                    Type listItemType = property.PropertyType.GetGenericArguments()[0];
                    IList list = (IList)Activator.CreateInstance(property.PropertyType);
                    object subObj = Activator.CreateInstance(listItemType);
                    SetDefaultValues(subObj);
                    list.Add(subObj);
                    property.SetValue(obj, list);
                }
                else
                {
                    object defaultValue = GetDefaultValue(property.PropertyType);
                    property.SetValue(obj, defaultValue);
                }
            }
        }

        private object GetDefaultValue(Type type)
        {
            if (type == typeof(string))
            {
                return type.Name;
            }
            else if (type == typeof(int))
            {
                return 0;
            }
            else if (type == typeof(double))
            {
                return 0.0;
            }
            else if (type == typeof(bool))
            {
                return false;
            }
            else if (type == typeof(DateTime))
            {
                return DateTime.MinValue;
            }
            else if (type.IsClass && type != typeof(string))
            {
                object subObj = Activator.CreateInstance(type);
                SetDefaultValues(subObj);
                return subObj;
            }
            else
            {
                return null;
            }
        }

        public Type GetVariableClassType(string variableClass)
        {
            return GetVariableClassTypes().First(x => x.FullName == variableClass);
        }

        /// <summary>
        /// 获取变量类所在程序集，获取的是Zhp.IService
        /// </summary>
        /// <returns></returns>
        private Type[] GetVariableClassTypes()
        {
            var type = typeof(IEmailVariable);

            return Assembly.GetAssembly(type).GetTypes().Where(x => type.IsAssignableFrom(x) && !x.IsInterface).ToArray();
        }
    }
}
